﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using WeSMsg.model;
using WeSMsg.util;
using System.Text.RegularExpressions;
using System.Data;
using System.Runtime.InteropServices;
using System.ServiceModel.Channels;
using System.Configuration;

namespace WeSMsg
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
   
    public class WeSMsg : IWeSMsg
    {

        [DllImport("Kernel32.dll", SetLastError = true)]
        static extern IntPtr OpenEvent(uint dwDesiredAccess, bool bInheritHandle, string lpName);

        [DllImport("kernel32.dll")]
        static extern bool SetEvent(IntPtr hEvent);

        const uint STANDARD_RIGHTS_REQUIRED = 0x000F0000;
        const uint SYNCHRONIZE = 0x00100000;
        const uint EVENT_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3);
        const UInt32 INFINITE = 0xFFFFFFFF;


        public MsgResultStatus requestIP()
        {
         
            OperationContext context = OperationContext.Current;
            MessageProperties messageProperties = context.IncomingMessageProperties;
            RemoteEndpointMessageProperty endpointProperty =
              messageProperties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;


            if (!checkAuthenticatedIp(endpointProperty.Address))
            {
                return new MsgResultStatus
                {
                    statusCode = MsgResultStatus.STATUS_UNALLOW_IP_CODE,
                    statusText = string.Format(MsgResultStatus.STATUS_UNALLOW_IP_TEXT, endpointProperty.Address)
                    
                };

            }
            else
            {
                return new MsgResultStatus
                {
                    statusCode = MsgResultStatus.STATUS_VALID_TOKEN_CODE,
                    statusText = MsgResultStatus.STATUS_VALID_TOKEN_TEXT
                };
            }
        }

        private bool checkAuthenticatedIp(string iP)
        {
            string whiteIP = ConfigurationManager.AppSettings["WhiteIPs"];
            whiteIP = whiteIP.Trim();
            string[] result = whiteIP.Split(';');
            
            foreach (string sub in result)
            {
                string t = sub.Trim();
                if (iP==t)
                    return true;
                  
            }
            return false;
            
        }
         

        public bool wakeUpWiSMsg()
        {
            IntPtr hdlOpen;
            hdlOpen = OpenEvent(EVENT_ALL_ACCESS, false, "Global\\WiSMsg");
            if (hdlOpen != IntPtr.Zero)
            {
                SetEvent(hdlOpen); //Wake up
                return true;
            }
            else
                return false;
        }

        public bool checkEmailAd(string address)
        {
            address = address.Trim();
            if (address == "")
            {
                return false;
            }
            else
            {

                string[] result = Regex.Split(address, ",");
                int flag = 0;
                foreach (string sub in result)
                {
                    string t = sub.Trim();
                    if (t != "")
                    {
                        flag = 1;
                        break;
                    }
                }
                if (flag == 0)
                {
                    return false;
                }
                foreach (string sub in result)
                {
                    string t = sub.Trim();

                    if (t != "" && Regex.IsMatch(t, @"\A(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\Z") == false)
                    {
                        return false;
                    }

                }
            }
            return true;
        }

        public bool downflag(int id)
        {
            return DB.exec("update EMAIL Set Flag = 0 where Id ="+id +" ;");
        }
        public WeSMsgEnqueueResult enqueue(Email email)
        {
            MsgResultStatus request = requestIP();
            if (request.statusCode == 0)
            {
                try
                {
                    if (checkEmailAd(email.emailTo) == true)
                    {
                       
                        object[,] parameter = { 
                                        {"@body",email.body},
                                        {"@emailFrom",email.emailFrom},
                                        {"@emailTo",email.emailTo},
                                        {"@subject",email.subject},
                                        {"@enqueueTime",DateTime.Now.ToString("yyyyMMddHHmmss")},
                                        {"@fileName",email.fileName},
                                        {"@isHTMLEncoded",email.isHTMLEncoded}               
                                      };

                        DB.exec("insert into Email (EmailFrom, EmailTo, [Subject], Body, EnqueueTime, [FileName], IsHTMLEncoded) values (@emailFrom, @emailTo, @subject, @body, @enqueueTime, @fileName, @isHTMLEncoded);", parameter);
                        wakeUpWiSMsg();
                        return new WeSMsgEnqueueResult
                        {
                            msgResultStatus = new MsgResultStatus
                            {
                                statusCode = MsgResultStatus.STATUS_VALID_TOKEN_CODE,
                                statusText = MsgResultStatus.STATUS_VALID_TOKEN_TEXT
                            }
                        };

                    }
                    else
                    {
                        return new WeSMsgEnqueueResult
                        {
                            msgResultStatus = new MsgResultStatus
                            {
                                statusCode = MsgResultStatus.STATUS_INVALID_EMAIL_CODE,
                                statusText = MsgResultStatus.STATUS_INVALID_EMAIL_TEXT
                            }
                        };
                    }
                }
                catch (Exception ex)
                {
                    return new WeSMsgEnqueueResult
                    {
                        msgResultStatus = new MsgResultStatus
                        {
                            statusCode = 500,
                            statusText = ex.Message
                        }
                    };
                }
            }
            else
            {

                return new WeSMsgEnqueueResult
                {
                    msgResultStatus = request
                };
            }
            
        }
        public WeSMsgDequeueResult dequeue()
        {

            try
            {
                Email emailnew = new Email();
                DataTable dt = null;
                dt = DB.getData("select top 1 * from EMAIL where DequeueTime is null");
                if (dt.Rows.Count == 0)
                {
                    return new WeSMsgDequeueResult
                    {
                        email = null,
                        msgResultStatus = new MsgResultStatus
                        {
                            statusCode = MsgResultStatus.STATUS_OUT_DEQUEUE_CODE,
                            statusText = MsgResultStatus.STATUS_OUT_DEQUEUE_TEXT
                        }

                    };

                }
                else
                {
                    emailnew.id = Convert.ToInt32(dt.Rows[0]["Id"]);
                    emailnew.emailTo = dt.Rows[0]["EmailTo"].ToString();
                    emailnew.subject = dt.Rows[0]["Subject"].ToString();
                    emailnew.body = dt.Rows[0]["Body"].ToString();
                    emailnew.dequeueTime = DateTime.Now.ToString("yyyyMMddHHmmss");
                    emailnew.enqueueTime = dt.Rows[0]["EnqueueTime"].ToString();
                    emailnew.fileName = dt.Rows[0]["FileName"].ToString();
                    emailnew.isHTMLEncoded = Convert.ToBoolean(dt.Rows[0]["IsHTMLEncoded"]);
                    object[,] parameter = { 
                                        {"@id",emailnew.id},
                                        {"@dequeueTime",DateTime.Now.ToString("yyyyMMddHHmmss")}
                                                       
                                      };
                    DB.exec("update EMAIL Set DequeueTime =@dequeueTime where Id =@id;", parameter);
                    return new WeSMsgDequeueResult
                    {
                        email = emailnew,
                        msgResultStatus = new MsgResultStatus
                        {
                            statusCode = MsgResultStatus.STATUS_VALID_TOKEN_CODE,
                            statusText = MsgResultStatus.STATUS_VALID_TOKEN_TEXT
                        }

                    };

                }
            }
            catch (Exception ex)
            {
                return new WeSMsgDequeueResult
                {
                    msgResultStatus = new MsgResultStatus
                    {
                        statusCode = 500,
                        statusText = ex.Message
                    }
                };
            }
        }
    }
}
